<template>
    <div class="dify-ai">
        <div class="chat-card">
            <div class="header">
                <div class="title">智能客服</div>
                <div class="header-right">
                    <div class="endpoint" title="接口地址">{{ endpointShown }}</div>
                    <div class="actions">
                        <button class="btn" :disabled="loading" @click="clearSession">清空对话</button>
                    </div>
                </div>
            </div>

            <div class="quickbar">
                <button class="chip" v-for="s in suggestions" :key="s" :disabled="loading" @click="quickSend(s)">{{ s
                }}</button>
            </div>

            <div class="messages" ref="messagesEl">
                <div v-for="(m, i) in messages" :key="i" class="message" :class="m.role">
                    <div class="avatar">{{ m.role === 'assistant' ? 'AI' : '你' }}</div>
                    <div class="bubble">{{ m.content }}</div>
                    <div class="ops">
                        <button class="copy" @click="copyMessage(m.content)">复制</button>
                    </div>
                </div>
                <div v-if="loading" class="message assistant">
                    <div class="avatar">AI</div>
                    <div class="bubble">正在思考...</div>
                </div>
            </div>

            <div class="composer">
                <textarea v-model="input" class="input"
                    :placeholder="loading ? '请稍候...' : '请输入消息，按 Enter 发送，Shift+Enter 换行'" :disabled="loading"
                    @compositionstart="isComposing = true" @compositionend="isComposing = false"
                    @keydown.enter.exact.prevent="onEnter" @keydown.enter.shift.stop />
                <button class="send" :disabled="!canSend" @click="send">{{ loading ? '发送中...' : '发送' }}</button>
                <button class="stop" v-if="loading" @click="stop">停止</button>
            </div>
        </div>
    </div>

</template>

<script setup lang="ts">
import { ref, onMounted, watch, nextTick, computed } from 'vue'
import { read, write } from '@/assets/Axios/axiosHttple'

type ChatRole = 'user' | 'assistant'
type Message = { role: ChatRole; content: string }

// 统一走 axiosHttple；优先写网关，其次读网关
const endpointCandidates = [
    'contractmanagementwrite/api/Dify/Chat',
    'contractmanagementread/api/Dify/Chat'
]
const endpointShown = endpointCandidates[0]

const messages = ref<Message[]>([])
const input = ref('')
const loading = ref(false)
const conversationId = ref<string | null>(null)
const userId = ref<string>('')
const messagesEl = ref<HTMLElement | null>(null)
const isComposing = ref(false)
const abortCtrl = ref<AbortController | null>(null)
const suggestions = ref<string[]>(['你好', '系统如何登录？', '如何重置密码？'])

onMounted(() => {
    const stored = localStorage.getItem('dify_user_id')
    if (stored) {
        userId.value = stored
    } else {
        userId.value = `u-${Math.random().toString(36).slice(2, 10)}`
        localStorage.setItem('dify_user_id', userId.value)
    }
    // 尝试加载本地持久化会话
    loadSession()
    // 如果首次无记录，加入欢迎语
    if (messages.value.length === 0) {
        messages.value.push({ role: 'assistant', content: '你好！有什么问题我可以帮你解答吗？' })
    }
})

watch(messages, async () => {
    await nextTick()
    if (messagesEl.value) {
        messagesEl.value.scrollTop = messagesEl.value.scrollHeight
    }
    saveSession()
})
watch(conversationId, () => saveSession())
watch(userId, () => loadSession())

const canSend = computed(() => !loading.value && input.value.trim().length > 0)

function getStorageKey() {
    return `dify_chat_${userId.value || 'default'}`
}

function saveSession() {
    try {
        const key = getStorageKey()
        const data = {
            conversationId: conversationId.value,
            messages: messages.value,
            lastUpdated: Date.now()
        }
        localStorage.setItem(key, JSON.stringify(data))
    } catch { }
}

function loadSession() {
    try {
        const key = getStorageKey()
        const raw = localStorage.getItem(key)
        if (!raw) return
        const data = JSON.parse(raw)
        if (Array.isArray(data?.messages)) {
            messages.value = data.messages
        }
        if (data?.conversationId) conversationId.value = data.conversationId
    } catch { }
}

function clearSession() {
    messages.value = []
    conversationId.value = null
    try { localStorage.removeItem(getStorageKey()) } catch { }
}

async function copyMessage(text: string) {
    try {
        await navigator.clipboard.writeText(text)
        alert('已复制')
    } catch {
        alert('复制失败')
    }
}

function onEnter() {
    if (isComposing.value) return
    send()
}

function quickSend(text: string) {
    if (loading.value) return
    input.value = text
    send()
}

async function send() {
    const text = input.value.trim()
    if (!text || loading.value) return

    input.value = ''
    messages.value.push({ role: 'user', content: text })
    loading.value = true
    try {
        abortCtrl.value = new AbortController()
        const body = {
            query: text,
            conversationId: conversationId.value,
            userId: userId.value,
            inputs: {}
        }
        let json: any = null
        let lastErr: any = null
        for (const ep of endpointCandidates) {
            try {
                const res = await write.post(ep, body, { signal: abortCtrl.value.signal })
                json = res?.data ?? null
                if (json != null) break
            } catch (e) {
                lastErr = e
            }
        }
        if (json == null) throw lastErr || new Error('请求失败')

        let answer = ''
        let newConvId: string | null = null

        if (json?.data != null) {
            try {
                const raw = typeof json.data === 'string' ? JSON.parse(json.data) : json.data
                answer = raw?.answer ?? JSON.stringify(raw)
                newConvId = raw?.conversation_id ?? raw?.conversationId ?? conversationId.value
            } catch {
                answer = String(json.data)
            }
        } else if (json?.message) {
            answer = String(json.message)
        } else {
            answer = '无响应'
        }

        if (newConvId) conversationId.value = newConvId
        messages.value.push({ role: 'assistant', content: answer })
    } catch (e: any) {
        if (e?.name === 'AbortError') {
            // 停止请求：不追加助手消息
        } else {
            messages.value.push({ role: 'assistant', content: `请求失败：${e?.message || e}` })
        }
    } finally {
        loading.value = false
        abortCtrl.value = null
    }
}

function stop() {
    try { abortCtrl.value?.abort() } catch { }
    loading.value = false
}
</script>

<style scoped>
.dify-ai {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    padding: 16px;
    /* 柔和渐变叠加：左上蓝紫、右上粉橙 + 底部浅色过渡 */
    background:
        radial-gradient(1200px 600px at 10% -10%, #e9f1ff 0%, rgba(233, 241, 255, 0) 60%),
        radial-gradient(1000px 500px at 90% 0%, #ffe9f2 0%, rgba(255, 233, 242, 0) 55%),
        radial-gradient(900px 380px at 50% 110%, #eef7ff 0%, rgba(238, 247, 255, 0) 60%),
        linear-gradient(180deg, #f9fbff 0%, #ffffff 70%);
}

.chat-card {
    width: 100%;
    max-width: 980px;
    display: flex;
    flex-direction: column;
    height: calc(100vh - 32px);
    max-height: 900px;
    border: 1px solid #eaeaea;
    border-radius: 12px;
    background: #fff;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06);
    overflow: hidden;
}

.header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid #eee;
    background: #fbfbfb;
}

.header-right {
    display: flex;
    gap: 12px;
    align-items: center;
}

.title {
    font-size: 16px;
    font-weight: 600;
}

.endpoint {
    font-size: 12px;
    color: #888;
    max-width: 60%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.actions .btn {
    height: 28px;
    padding: 0 10px;
    border: 1px solid #ddd;
    background: #fff;
    border-radius: 6px;
    cursor: pointer;
}

.actions .btn:disabled {
    opacity: .6;
    cursor: not-allowed;
}

.messages {
    flex: 1;
    padding: 16px;
    overflow-y: auto;
    background: #fafafa;
}

.message {
    display: flex;
    margin-bottom: 10px;
}

.message.user {
    justify-content: flex-end;
}

.message.assistant {
    justify-content: flex-start;
}

.bubble {
    max-width: 70%;
    padding: 10px 12px;
    border-radius: 10px;
    white-space: pre-wrap;
    word-break: break-word;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

.avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: #e6f0ff;
    color: #3464ff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    margin-right: 8px;
}

.ops {
    display: flex;
    align-items: center;
    margin-left: 8px;
    opacity: 0;
    transition: opacity .2s ease;
}

.message:hover .ops {
    opacity: 1;
}

.copy {
    height: 24px;
    padding: 0 8px;
    border: 1px solid #ddd;
    background: #fff;
    border-radius: 4px;
    cursor: pointer;
    font-size: 12px;
}

.message.user .bubble {
    background: #4f7cff;
    color: #fff;
    border-top-right-radius: 4px;
}

.message.assistant .bubble {
    background: #fff;
    color: #333;
    border: 1px solid #eee;
    border-top-left-radius: 4px;
}

.composer {
    display: flex;
    gap: 8px;
    padding: 12px;
    border-top: 1px solid #eee;
    background: #fff;
}

.input {
    flex: 1;
    min-height: 60px;
    max-height: 160px;
    resize: vertical;
    padding: 8px 10px;
    border: 1px solid #ddd;
    border-radius: 8px;
    outline: none;
}

.send {
    padding: 0 16px;
    border: none;
    border-radius: 8px;
    background: #4f7cff;
    color: #fff;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(79, 124, 255, .25);
}

.send:disabled {
    background: #b9c5ff;
    cursor: not-allowed;
}

.stop {
    padding: 0 16px;
    border: none;
    border-radius: 8px;
    background: #ff4d4f;
    color: #fff;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(255, 77, 79, .25);
}

.quickbar {
    display: flex;
    gap: 8px;
    padding: 8px 16px;
    border-bottom: 1px dashed #eee;
    background: #fff;
}

.chip {
    height: 28px;
    padding: 0 10px;
    border: 1px solid #e5eaf5;
    background: #f5f8ff;
    color: #3a5ce0;
    border-radius: 999px;
    cursor: pointer;
}
</style>
